///////////////////////////////////////////////////////////////////////////////
// vrtraverse.h																															 //
//																																					 //
// Author: Alexander Bogomjakov																							 //
///////////////////////////////////////////////////////////////////////////////

#ifndef _VRTRAVERSE_H_
#define _VRTRAVERSE_H_

#include "vr.h"


///////////////////////////////////////////////////////////////////////////////
// VRTraverse																																 //
///////////////////////////////////////////////////////////////////////////////

class VRTraverse {
public:
	void traverse(VRNode *root);

protected:
	virtual bool nodePreFunc (VRNode*) = 0;
	virtual bool nodePostFunc(VRNode*) = 0;
};


///////////////////////////////////////////////////////////////////////////////
// CVRTraverse																															 //
///////////////////////////////////////////////////////////////////////////////

template <class T>
class CVRTraverse : public VRTraverse {
public:
	CVRTraverse(T*, bool (T::*pNodePreFunc) (VRNode*),
		        bool (T::*pNodePostFunc)(VRNode*) = NULL);
	CVRTraverse(T*, void (T::*pNodePreFunc) (VRNode*),
			void (T::*pNodePostFunc)(VRNode*) = NULL);
	CVRTraverse(T*, bool (T::*pNodePreFunc) (VRNode*),
			void (T::*pNodePostFunc)(VRNode*));

// Implementation
protected:
	virtual bool nodePreFunc (VRNode*);
	virtual bool nodePostFunc(VRNode*);

protected:
	T				 *m_pTObj;
	bool (T::*m_pNodePreFuncBool) (VRNode*);
	bool (T::*m_pNodePostFuncBool)(VRNode*);
	void (T::*m_pNodePreFuncVoid) (VRNode*);
	void (T::*m_pNodePostFuncVoid)(VRNode*);
};

///////////////////////////////////////////////////////////////////////////////
// Implementation of CVRTraverse																						 //
///////////////////////////////////////////////////////////////////////////////

template <class T>
CVRTraverse<T>::CVRTraverse(T *pTObj, bool (T::*pNodePreFunc) (VRNode*),
																			bool (T::*pNodePostFunc)(VRNode*))
: m_pTObj(pTObj)
, m_pNodePreFuncBool (pNodePreFunc)
, m_pNodePostFuncBool(pNodePostFunc)
, m_pNodePreFuncVoid (NULL)
, m_pNodePostFuncVoid(NULL)
{
}


template <class T>
CVRTraverse<T>::CVRTraverse(T *pTObj, void (T::*pNodePreFunc) (VRNode*),
																			void (T::*pNodePostFunc)(VRNode*))
: m_pTObj(pTObj)
, m_pNodePreFuncBool (NULL)
, m_pNodePostFuncBool(NULL)
, m_pNodePreFuncVoid (pNodePreFunc)
, m_pNodePostFuncVoid(pNodePostFunc)
{
}


template <class T>
CVRTraverse<T>::CVRTraverse(T *pTObj, bool (T::*pNodePreFunc) (VRNode*),
																			void (T::*pNodePostFunc)(VRNode*))
: m_pTObj(pTObj)
, m_pNodePreFuncBool (pNodePreFunc)
, m_pNodePostFuncBool(NULL)
, m_pNodePreFuncVoid (NULL)
, m_pNodePostFuncVoid(pNodePostFunc)
{
}


template <class T>
bool CVRTraverse<T>::nodePreFunc(VRNode *node)
{
	if (m_pNodePreFuncBool)
		return (m_pTObj->*m_pNodePreFuncBool)(node);

	(m_pTObj->*m_pNodePreFuncVoid)(node);

	return true;
}


template <class T>
bool CVRTraverse<T>::nodePostFunc(VRNode *node)
{
	if (m_pNodePostFuncBool)
		return (m_pTObj->*m_pNodePostFuncBool)(node);

	if (m_pNodePostFuncVoid)
		(m_pTObj->*m_pNodePostFuncVoid)(node);

	return true;
}

#endif